package com.dyzx.hbb.modules.sys.controller;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONObject;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dyzx.hbb.common.base.PageQuery;
import com.dyzx.hbb.common.base.PageResult;
import com.dyzx.hbb.common.base.Result;
import com.dyzx.hbb.common.config.MyLambdaQueryWrapper;
import com.dyzx.hbb.common.utils.DateFormat;
import com.dyzx.hbb.common.utils.Utils;
import com.dyzx.hbb.modules.sys.entity.SysDictValue;
import com.dyzx.hbb.modules.sys.entity.SysFile;
import com.dyzx.hbb.modules.sys.query.FileQuery;
import com.dyzx.hbb.modules.sys.service.SysDictValueService;
import com.dyzx.hbb.modules.sys.service.SysFileService;
import com.dyzx.hbb.security.context.SecurityContextHolder;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;

import java.io.File;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author Hesenjan(Serkol)
 * @since 2021-11-18
 */
@Tag(name = "09.对象存储", description = "对象存储相关接口")
@RestController
@CrossOrigin
@RequestMapping("/sys/file")
public class FileController {
    @Value(value = "${aliyun.oss.bucket}")
    private String bucket;
    @Autowired
    private OSS aliyunOSSClient;
    @Autowired
    private SysFileService fileService;
    @Autowired
    private SysDictValueService valueService;
    @Value("${aliyun.oss.host}")

    private String uploadOsshost;

    @Value("${file.upload.host}")
    private String uploadhost;
    @Value("${file.upload.path}")
    private String uploadpath;
    @Value("${file.upload.disk}")
    private int disk;


    private static String getFileExtension(String name) {
        int extIndex = name.lastIndexOf(".");
        if (extIndex == -1) {
            return "png";
        } else {
            return name.substring(extIndex + 1);
        }
    }

    private static boolean isImage(String name) {
        String fileExtension = getFileExtension(name);
        return fileExtension.equals("jpg") || fileExtension.equals("jpeg") || fileExtension.equals("png") || fileExtension.equals("gif");
    }

    @Operation(summary = "上传文件")
    @Parameters({
            @Parameter(name = "file", description = "文件上传", required = true),
            @Parameter(name = "type", description = "类型")
    })
    @PostMapping(value = "", headers = "content-type=multipart/form-data")
    public Result<SysFile> upload(
            @RequestParam(name = "file") MultipartFile file,
            @RequestParam(name = "type", defaultValue = "0") int type) throws IOException {
        System.out.println("File Type:" + type);
        // 方法体保持不变
        if (type == 0) {
            return Result.error("请选择文件类型");
        }
        if(file.isEmpty()){
            return Result.error("文件为空");
        }
        Result<SysFile> result = new Result<>();
        List<SysDictValue> byMapKey = valueService.findByListKey("sys_file_type");
        List<SysDictValue> collectFile = byMapKey.stream().filter(s -> s.getValue() == type).toList();

      //  System.out.println(byMapKey);

        if (collectFile.isEmpty()) {
            System.out.println("字典表数据为空");
            return Result.error("请先配置文件类型0");
        }

        SysDictValue sysDictValue =collectFile.get(0);
        String folder = sysDictValue.getParam();
        System.out.println("File:" + folder);
        folder = folder.replaceAll(",", "").trim();
        if (StringUtils.isEmpty(folder)) {
            folder = "public";
        }
        long request_id = System.currentTimeMillis();
        System.out.println("File:" + file.isEmpty());
        if (file.isEmpty()) {
            return Result.error("文件为空");
        }
        SysFile pictures = new SysFile();

        pictures.setDisk(disk);

        pictures.setType(type);
        if (isImage(file.getOriginalFilename())) {
            BufferedImage bi = ImageIO.read(file.getInputStream());
            if (bi != null) {
                pictures.setHeight(bi.getHeight());
                pictures.setWidth(bi.getWidth());
            }
        }
        String format = DateUtil.format(new Date(), "yyyyMM");
        String typeExt = getFileExtension(Objects.requireNonNull(file.getOriginalFilename()));
        // String filem = folder + "/"+format+"/";
        Long organId = SecurityContextHolder.getOrganId();
        String filem = organId + "/" + folder + "/";
        Random random = new Random();
        int i1 = random.nextInt(1000000000);
        String fileName = filem + String.valueOf(System.currentTimeMillis()) + i1 + "." + typeExt;
        try {

            if (disk == 1) {
                PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, fileName, file.getInputStream());
                PutObjectResult result1 = aliyunOSSClient.putObject(putObjectRequest);
                result.setData(result1);
            } else {
                File file1 = new File(uploadpath + filem);
                if (!file1.exists()) {
                    file1.mkdirs();
                }
                File dest = new File(uploadpath + fileName);
                file.transferTo(dest);
                uploadOsshost = uploadhost;
            }

            pictures.setName(Utils.quoteReplacement(file.getOriginalFilename()));
            //pictures.setIstype(0);
            pictures.setExt(typeExt);
            pictures.setUrl(fileName);

            //  pictures.setRequestId((request_id + i1));
            boolean edit = fileService.save(pictures);
            if (edit) {
                //    String pathname = uploadhost + "/" + pictures.getUrl();
                //    pictures.setUrl(pathname);

                Map<String, Object> picturesMap = new HashMap<>();
                picturesMap.put("id", pictures.getId());
                picturesMap.put("name", pictures.getName());
                picturesMap.put("ext", pictures.getExt());
                picturesMap.put("url", uploadOsshost + pictures.getUrl());


                result.setData(picturesMap);
                result.setMsg("上传成功");
                result.setCode(200);
            } else {
                result.setMsg("上传失败");
            }

        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
            result.setMsg("上传失败");
            result.setData(oe);
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
            result.setData(ce);
        } catch (IOException e) {
            //  throw new RuntimeException(e);
            result.setData(e);
        }

        return result;
    }
/*    @Operation(summary = "文件编辑")
    @PutMapping
    public Result<Boolean> edit(@RequestBody SysFile file) {
        return Result.ok(fileService.updateById(file));
    }*/

    @Operation(summary = "文件详情")
    @GetMapping("/{id}")
    public Result<Map<String, Object>> detail(@RequestParam Long id) {

        // SysFile byId = fileService.getById(id);

        MyLambdaQueryWrapper<SysFile> queryWrapper = new MyLambdaQueryWrapper<>();
        queryWrapper.eq(SysFile::getId, id);
        queryWrapper.select(SysFile::getId)
                .select(SysFile::getName)
                .select(SysFile::getExt)
                .select(SysFile::getType)
                .select(SysFile::getDisk)
                .select(SysFile::getHeight)
                .select(SysFile::getWidth)
                .select(SysFile::getUrl)
                .select(SysFile::getStatus)
                .select(SysFile::getCreateDate)
                .select(SysFile::getOperatorId)
                .userName(SysFile::getOperatorId).as("operator_name")
                .organName(SysFile::getOrganId).as("organ_name")

                .select(SysFile::getUpdateDate);

        queryWrapper.eq(SysFile::getId, id).last("limit 1");
        Map<String, Object> map = fileService.getMap(queryWrapper);
        return Result.ok(map);
    }

    @Operation(summary = "文件删除")
    @DeleteMapping("/{id}")
    public Result<Boolean> delete(@PathVariable Long id) {
        SysFile byId = fileService.getById(id);

        if (byId == null) {
            return Result.error("文件不存在");
        }
        boolean flag = fileService.removeById(id);
        if (flag) {
            if (byId.getDisk() == 1) {
                aliyunOSSClient.deleteObject(bucket, byId.getUrl());
            }
        }
        return flag ? Result.ok() : Result.error();

    }

    @Operation(summary = "文件列表")
    @GetMapping("/list")
    public PageResult<Map<String, Object>> list(PageQuery query, FileQuery fileQuery) {
        MyLambdaQueryWrapper<SysFile> queryWrapper = new MyLambdaQueryWrapper<>();
        queryWrapper.select(SysFile::getId)
                .select(SysFile::getName)
                .select(SysFile::getExt)
                .select(SysFile::getType)
                .select(SysFile::getDisk)
                .select(SysFile::getHeight)
                .select(SysFile::getWidth)
                .select(SysFile::getUrl)
                .select(SysFile::getStatus)
                .select(SysFile::getCreateDate);

        queryWrapper.likeRight(StringUtils.isNotBlank(fileQuery.getName()), SysFile::getName, fileQuery.getName())
                .eq(StringUtils.isNotBlank(fileQuery.getExt()), SysFile::getExt, fileQuery.getExt())
                .eq(fileQuery.getType() != null, SysFile::getType, fileQuery.getType())
                .eq(fileQuery.getDisk() != null, SysFile::getDisk, fileQuery.getDisk())
                .eq(fileQuery.getStatus() != null, SysFile::getStatus, fileQuery.getStatus())
                .dateBetween(StringUtils.isNotBlank(fileQuery.getCreateDate()), SysFile::getCreateDate, DateFormat.DATE, fileQuery.getCreateDate());
        Page<Map<String, Object>> page = fileService.pageMaps(query.toPage(), queryWrapper);
        return PageResult.parsePage(page);
    }

    @Operation(summary = "获取文件地址")
    @GetMapping("/path")
    public Result<String> getPath(@RequestParam String ids) {
        Result<String> result = new Result<>();
        if (StringUtils.isNotEmpty(ids)) {
            System.out.println(ids);
            String[] idsd = ids.split(",");
            //  long[] idsd = StrUtil.splitToLong(",", ids);

            if (idsd.length > 0) {
                MyLambdaQueryWrapper<SysFile> queryWrapper = new MyLambdaQueryWrapper<>();
                queryWrapper.in(SysFile::getId, idsd);
                queryWrapper.select(SysFile::getUrl);
                List<Object> mapList = fileService.listObjs(queryWrapper);

                if (!mapList.isEmpty()) {

                    List<String> urls = mapList.stream().map(item -> (String) (uploadOsshost) + item).collect(Collectors.toList());
                    Map<String, Object> map = new HashMap<>();
                    map.put("url", uploadOsshost);


                    map.put("images", mapList);
                    result.setCode(200);
                    result.setData(urls);

                    return result;
                } else {
                    return Result.error("文件不存在");
                }
            } else {
                return Result.error("参数错误");
            }
        } else {
            return Result.error("参数错误");
        }

    }

    @Operation(summary = "文件清理")
    @DeleteMapping("/clean")
    public Result<Boolean> clean() {
        MyLambdaQueryWrapper<SysFile> queryWrapper = new MyLambdaQueryWrapper<>();
        // 查询三个月前且已删除的文件
        Date threeMonthsAgo = DateUtil.offsetMonth(new Date(), -3);
        queryWrapper.eq(SysFile::getDisk, 1)
                .eq(SysFile::getDeleted, 1)
                .lt(SysFile::getCreateDate, threeMonthsAgo);

        List<SysFile> list = fileService.list(queryWrapper);
        if (!list.isEmpty()) {
            for (SysFile file : list) {
                try {
                    aliyunOSSClient.deleteObject(bucket, file.getUrl());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return Result.ok(fileService.remove(queryWrapper));
        }
        return Result.ok(true);
    }


}

